home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / db / esm-3.1 / esm-3 / usr / local / sm / src / serverlib / redo / redoPageAllocation.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-05  |  9.6 KB  |  357 lines

  1. /*
  2.  *   $RCSfile: redoPageAllocation.c,v $  
  3.  *   $Revision: 1.1.1.1 $  
  4.  *   $Date: 1996/05/04 21:55:55 $      
  5.  */ 
  6. /**********************************************************************
  7. * EXODUS Database Toolkit Software
  8. * Copyright (c) 1991 Computer Sciences Department, University of
  9. *                    Wisconsin -- Madison
  10. * All Rights Reserved.
  11. *
  12. * Permission to use, copy, modify and distribute this software and its
  13. * documentation is hereby granted, provided that both the copyright
  14. * notice and this permission notice appear in all copies of the
  15. * software, derivative works or modified versions, and any portions
  16. * thereof, and that both notices appear in supporting documentation.
  17. *
  18. * THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY OF WISCONSIN --
  19. * MADISON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.  
  20. * THE DEPARTMENT DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
  21. * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  22. *
  23. * The EXODUS Project Group requests users of this software to return 
  24. * any improvements or extensions that they make to:
  25. *
  26. *   EXODUS Project Group 
  27. *     c/o David J. DeWitt and Michael J. Carey
  28. *   Computer Sciences Department
  29. *   University of Wisconsin -- Madison
  30. *   Madison, WI 53706
  31. *
  32. *     or exodus@cs.wisc.edu
  33. *
  34. * In addition, the EXODUS Project Group requests that users grant the 
  35. * Computer Sciences Department rights to redistribute these changes.
  36. **********************************************************************/
  37.  
  38.  
  39. #include "sysdefs.h"
  40. #include "ess.h"
  41. #include "checking.h"
  42. #include "trace.h"
  43. #include "error.h"
  44. #include "list.h"
  45. #include "pool.h"
  46. #include "tid.h"
  47. #include "io.h"
  48. #include "lock.h"
  49. #include "object.h"
  50. #include "msgdefs.h"
  51. #include "thread.h"
  52. #include "latch.h"
  53. #include "semaphore.h"
  54. #include "link.h"
  55. #include "lsn.h"
  56. #include "bf.h"
  57. #include "log.h"
  58. #include "volume.h"
  59. #include "logrecs.h"
  60. #include "trans.h"
  61. #include "bitmap.h"
  62. #include "openlog.h"
  63. #include "logaction.h"
  64. #include "io_extfuncs.h"
  65. #include "bf_extfuncs.h"
  66. #include "bm_extfuncs.h"
  67. #include "trans_extfuncs.h"
  68. #include "redo_extfuncs.h"
  69. #include "util_funcs.h"
  70. #include "thread_globals.h"
  71. #include "log_globals.h"
  72. #include "log_extfuncs.h"
  73.  
  74.  
  75.  void
  76. redoPageAllocation (
  77.  
  78.     LOGRECORDHDR            *record 
  79. )
  80. {
  81.  
  82.     register VOLREC            *volRec;
  83.     register PID            *pid;
  84.     register int            i;    
  85.     register GROUPLINK        *groupLink;
  86.     register DIRTYPAGEINFO    *dirtyInfo;
  87.     BITMAPPAGE                *bitmapPage;
  88.     PID                        bitmapPid;
  89.     PID                        volHdrPid;
  90.     LRC                        *lrcList;
  91.     int                        bitmapPageCount;
  92.     int                        allocPageCount;    /* # of pages allocated */
  93.     LRC                        *headerLRC;        /* volume header lrc     */
  94.     SHORTPID                allocPage;
  95.     int                        bitsToSet;        /* # bits to set on page*/ 
  96.     int                        totalBitsToSet;
  97.     int                        bitsSetSoFar;
  98.     int                        bit;
  99.     PAGEALLOCINFO            *pageAllocInfo;
  100.  
  101.  
  102.     TRPRINT(TR_IO|TR_LOG, TR_LEVEL_1, ("lsn:%d", record->recordLSN.offset));
  103.  
  104.     /*
  105.       *    Initially there is no volume info
  106.      */
  107.     volRec = NULL;
  108.  
  109.     /*
  110.      *    get a pointer to the common page allocation info
  111.      */
  112.     pageAllocInfo = (PAGEALLOCINFO *) GET_LOG_IMAGE(record, 0);
  113.     TRPRINT(TR_IO|TR_LOG, TR_LEVEL_2, ("numPages:%d", pageAllocInfo->numPages));
  114.  
  115.     /*
  116.      *    get a pointer to the name in the record, and the number of
  117.      *    pages allocated.
  118.      */
  119.     pid = (PID *) GET_LOG_IMAGE(record, 1);
  120.     allocPageCount = GET_LOG_IMAGE_SIZE(record, 1) / sizeof(PID);
  121.     SM_ASSERT(LEVEL_3, pageAllocInfo->numPages == allocPageCount);
  122.     TRPRINT(TR_IO|TR_LOG, TR_LEVEL_2, ("pid:%d", pid->page));
  123.  
  124.     /*
  125.      *    get a pointer to the lrc list for the bitmap pages, and
  126.      *    calculate the number of bitmap pages involved, base on
  127.      *    the length of the list
  128.      */
  129.     lrcList = (LRC *) GET_LOG_IMAGE(record, 2);
  130.     bitmapPageCount = GET_LOG_IMAGE_SIZE(record, 2) / sizeof(LRC);
  131.     TRPRINT(TR_RECOVER, TR_LEVEL_2, ("lrc list size:%d", bitmapPageCount));
  132.  
  133.     /*
  134.      *  get a pointer to the volume header lrc
  135.      */
  136.     headerLRC = &(pageAllocInfo->headerLRC);
  137.     TRPRINT(TR_RECOVER, TR_LEVEL_2, ("header lrc:%d", headerLRC->count));
  138.  
  139.     /*
  140.      *    set the volume id of the bitmap pid
  141.      */
  142.     bitmapPid.volid = pid->volid;
  143.  
  144.     /*
  145.      *    Reallocate the bits on each bitmap paget
  146.      */
  147.     allocPage = pid->page;  /* first allocated page */
  148.     totalBitsToSet = allocPageCount * BLOCKCOUNT(pageAllocInfo->page2size);
  149.     bitsSetSoFar = 0;
  150.     for (i = 0; i < bitmapPageCount; i++)    {
  151.  
  152.         /*
  153.          *    calculate the bitmap page
  154.          */
  155.         bitmapPid.page = BIT_TO_PAGE(allocPage) + pageAllocInfo->firstBitmapPage;
  156.         TRPRINT(TR_RECOVER, TR_LEVEL_2, ("bitmap page:%d", bitmapPid.page));
  157.  
  158.         /*
  159.          *    check to see if the page is in the dirty list
  160.          */
  161.         if ((dirtyInfo = searchDirtyPageTable( &bitmapPid )) == NULL)    {
  162.  
  163.             /*
  164.              *    don't need to redo the entry
  165.              */
  166.             TRPRINT(TR_RECOVER, TR_LEVEL_2, ("page not in table"));
  167.             continue;
  168.         }
  169.  
  170.         /*
  171.          *    check to see if the lrc on the page is greater than
  172.          *    the lrc in the log record
  173.          */
  174.         if (CHECK_PAGE_LRC_LESS_DIRTYINFO(lrcList[i], record->recordLSN, dirtyInfo)) {
  175.  
  176.             /*
  177.              *    don't need to redo
  178.              */
  179.             TRPRINT(TR_RECOVER, TR_LEVEL_2, ("dirty info page lrc later"));
  180.             continue;
  181.         }
  182.  
  183.  
  184.         if (volRec == NULL) {
  185.             if ((volRec = io_FindVolRec(pid->volid)) == NULL) {
  186.  
  187.                 SM_ERROR(TYPE_FATAL, Active->errno);
  188.             }
  189.             SM_ASSERT(LEVEL_3, pageAllocInfo->firstBitmapPage == volRec->header->freeBitmapAddr);
  190.         }
  191.  
  192.         /*
  193.          *    read in the page
  194.          */
  195.         if ((groupLink = bf_ReadPage(volRec->bufGroup, &bitmapPid,
  196.                                      BITMAP_PAGE2SIZE, BF_SEM)) == NULL)    {
  197.  
  198.             SM_ERROR(TYPE_FATAL, esmINTERNAL);
  199.         }
  200.  
  201.         /*
  202.          *    get a pointer to the bitmap page
  203.          */
  204.         bitmapPage = (BITMAPPAGE *) groupLink->bufFrame;
  205.  
  206.         /*
  207.          *    check to see if the lrc on the page is greater than
  208.          *    the lrc in the log record
  209.          */
  210.         if (compareLRC( &(lrcList[i]), &(bitmapPage->lrc)) <= 0)    {
  211.  
  212.             /*
  213.              *    don't need to redo
  214.              *    mark the page lrc
  215.              */
  216.             TRPRINT(TR_RECOVER, TR_LEVEL_2, ("actual page lrc later"));
  217.             dirtyInfo->lrc = bitmapPage->lrc;
  218.  
  219.             /*
  220.              *    release the page, not dirty
  221.              */
  222.             signalSemaphore( &(groupLink->pageHash->semaphore) );
  223.             bf_UnfixPage(groupLink, BF_DEFAULT, FALSE);
  224.             continue;
  225.         }
  226.  
  227.         /*
  228.          *    The number of bits to set is either the number left on
  229.          *    the bitmap page or the number of pages left to mark
  230.          *    allocated, whichever is smaller.
  231.          */
  232.         bitsToSet = (int) MIN((BITS_IN_PAGE - BIT_IN_PAGE(allocPage)), 
  233.                         (totalBitsToSet - bitsSetSoFar) );
  234.         bitsSetSoFar += bitsToSet;
  235.         SM_ASSERT(LEVEL_3, allocPageCount >= (allocPage - pid->page));
  236.  
  237.         /*
  238.          *     clear all necessary bits for this bitmap page
  239.          */
  240.         for (bit = (int) BIT_IN_PAGE(allocPage); 
  241.              bit < (BIT_IN_PAGE(allocPage)+bitsToSet); bit++) {
  242.  
  243.             /*
  244.              *    actually set the bit
  245.              */
  246.             bm_ClearBit((UFOUR *) groupLink->bufFrame, (FOUR) BIT_IN_PAGE(bit));
  247.         }
  248.  
  249.         /*
  250.          *    set the page lrc
  251.          *    Set up the firstLSN/LRC for the page
  252.          */
  253.         bitmapPage->lrc = lrcList[i];
  254.         DEPEND_LOG(groupLink->pageHash, 0, &(record->recordLSN), (lrcList+i));
  255.         TRPRINT(TR_RECOVER, TR_LEVEL_2, ("marking new page lrc:%d", bitmapPage->lrc.count));
  256.  
  257.         /* 
  258.          *    free and dirty the page
  259.          */
  260.         signalSemaphore( &(groupLink->pageHash->semaphore) );
  261.         bf_UnfixPage(groupLink, BF_DEFAULT, TRUE);
  262.  
  263.         /*
  264.          *    Calculate index of the first allocated page on the next
  265.          *    bitmap page. 
  266.          */
  267.         allocPage += BITS_IN_PAGE - BIT_IN_PAGE(allocPage);
  268.     }
  269.  
  270.     /*
  271.      *  Redo the decrement to the numFreePages field on the volume
  272.      *     header if necessary.  First, get the header page pid.
  273.      */
  274.     volHdrPid.page = HEADERADDR;
  275.     volHdrPid.volid = pid->volid;
  276.  
  277.     /*
  278.      *  check to see if the page is in the dirty page list
  279.      */
  280.     if ((dirtyInfo = searchDirtyPageTable(&volHdrPid)) == NULL)    {
  281.  
  282.         /*
  283.          *  don't need to redo
  284.          */
  285.         TRPRINT(TR_RECOVER, TR_LEVEL_2, ("dirty page not present"));
  286.         return;
  287.     }
  288.  
  289.     if (volRec == NULL)  {
  290.         if ((volRec = io_FindVolRec(volHdrPid.volid)) == NULL)    {
  291.  
  292.             SM_ERROR(TYPE_FATAL, Active->errno);
  293.         }
  294.         SM_ASSERT(LEVEL_3, pageAllocInfo->firstBitmapPage == volRec->header->freeBitmapAddr);
  295.     }
  296.  
  297. #ifdef DEBUG
  298.     /*
  299.      *  check to see if the lrc on the page is greater than
  300.      *  the lrc in the log record
  301.      *    NOTE: this comparison is not strictly necessary, since the
  302.      *    header page is always resident and the next comparison
  303.      *    count be made instead.
  304.      */
  305.     if (compareLRC( headerLRC, &(dirtyInfo->lrc) ) < 0)  {
  306.  
  307.         /*
  308.          *  don't need to redo
  309.          */
  310.         TRPRINT(TR_RECOVER, TR_LEVEL_2, ("dirty info page lrc later"));
  311.         return;
  312.     }
  313.  
  314.     /*
  315.      *  Make sure the comparison was correct
  316.      */
  317.     SM_ASSERT(LEVEL_3, compareLSN( &(record->recordLSN), &(dirtyInfo->lsn)) >= 0);
  318. #endif DEBUG
  319.  
  320.     /*
  321.      *  check to see if the lrc on the header page is greater than
  322.      *  the lrc in the log record
  323.      */
  324.     if (compareLRC( headerLRC, &volRec->header->lrc) <= 0)    {
  325.  
  326.         /*
  327.          *  don't need to redo
  328.          *  mark the page lrc, and return
  329.          */
  330.         TRPRINT(TR_RECOVER, TR_LEVEL_2, ("actual page lrc later"));
  331.         dirtyInfo->lrc = volRec->header->lrc;
  332.  
  333.         return;
  334.     }
  335.  
  336.     /*
  337.       *    The volume header needs to be updated, so decrement the number
  338.      *    of free pages by the number allocated.
  339.      */
  340.     if (waitSemaphore(&(volRec->headerLink->pageHash->semaphore)) != esmNOERROR) {
  341.         SM_ERROR(TYPE_FATAL, esmINTERNAL);
  342.     }
  343.     io_ChangeVolFreePages(volRec, -totalBitsToSet);
  344.  
  345.     /*
  346.      *  mark the LRC on the header page and dirty the page
  347.      *    Set up the firstLSN/LRC for the page
  348.      *    Release the semaphore on the volume header
  349.      */
  350.     volRec->header->lrc = *headerLRC;
  351.     DEPEND_LOG(volRec->headerLink->pageHash, 0, &(record->recordLSN), headerLRC);
  352.     TRPRINT(TR_RECOVER, TR_LEVEL_2, ("marking header page lrc:%d", volRec->header->lrc.count));
  353.     signalSemaphore(&(volRec->headerLink->pageHash->semaphore));
  354.  
  355.     return;
  356. }
  357.